<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title>setInterval(s, i) vs. setTimeout(s, i)</title>
<style type="text/css" media="screen">
#rocket {
	position: absolute;
	visibility: hidden;
	top: 0;
	left: 0;
	background: blue;
	border: 3px groove teal;
	height: 40px;
	width: 40px;
}
</style>
<script type="text/javascript" defer="defer">
	function doInterval(id) {
		var ew = ElementWrapper.getInstance(id);
		if (ew.getLock()) {
			ew.css.visibility = "visible";
			var t0 = new Date().getTime();
			ew.ondonemoving = function() {
				this.moveToLeft0();
				ew.ondonemoving = function() {
					document.getElementById("monitor1").innerHTML = ("setInterval(s, i) took: " + (new Date()
							.getTime() - t0));
					this.releaseLock();
				};
			};
			// start the animation.
			ew.moveToRight600();
		}
	}
	function doTimeout(id) {
		var ew = ElementWrapper.getInstance(id);
		if (ew.getLock()) {
			ew.css.visibility = "visible";
			var t0 = new Date().getTime();
			ew.ondonemoving = function() {
				ew.moveToLeft0Timeout();
				ew.ondonemoving = function() {
					document.getElementById("monitor2").innerHTML = ("setTimeout(s, i) took: " + (new Date()
							.getTime() - t0));
					this.releaseLock();
				};
			};
			// start the animation.
			ew.moveToRight600Timeout();
		}
	}
	ElementWrappers = {};
	ElementWrapper = function(el) {
		this.el = el;
		this.id = el.id;
		this.css = this.el.style; // shorten object chain.
		// use parseInt here once to avoid repeated calls in moveTo.
		this.x = parseInt(this.css.left) || 0;
		this.y = parseInt(this.css.top) || 0;
		ElementWrappers[this.id] = this;
	};	
	ElementWrapper.getInstance = function(id) {
		if(!(ElementWrappers[id])){
			ElementWrappers[id] = new ElementWrapper(document.getElementById(id));
		}
		return ElementWrappers[id];
	};
	ElementWrapper.prototype = {

		animTimer : 0,
		isBlocked : false,

		id : null,
		css : {},
		x : 0,
		y : 0,

		/**
		 * Moves the element to a pixel coordinate.
		 * This works, but is not optimally efficient.
		 */
		moveTo : function(x, y) {
			// inlining assignment for faster performance.
			this.css.left = (this.x = x) + "px";
			this.css.top = (this.y = y) + "px";
		},
		moveBy : function(x, y) {
			// inlining assignment for faster performance.
			this.css.left = (this.x += x) + "px";
			this.css.top = (this.y += y) + "px";
		},

		moveToRight600 : function() {
			this.animTimer = setInterval("ElementWrappers." + this.id
					+ ".moveRight600()", 1);
		},
		moveToLeft0 : function() {
			this.animTimer = setInterval("ElementWrappers." + this.id
					+ ".moveLeft0()", 1);
		},

		moveToRight600Timeout : function() {
			if (this.x >= 600) {
				this.ondonemoving();
				return;
			}

			this.moveBy(2, 0);
			setTimeout("ElementWrappers." + this.id + ".moveToRight600Timeout()", 1);
		},

		moveToLeft0Timeout : function() {
			if (this.x <= 0) {
				this.ondonemoving();
				return;
			}
			this.moveBy(-2, 0);
			setTimeout("ElementWrappers." + this.id + ".moveToLeft0Timeout()",1);
		},

		moveLeft0 : function() {
			if (this.x <= 0) {
				clearInterval(this.animTimer);
				this.ondonemoving();
			}
			this.moveBy(-2, 0);
		},
		moveRight600 : function() {
			if (this.x >= 600) {
				clearInterval(this.animTimer);
				this.ondonemoving();
			}
			this.moveBy(2, 0);
		},

		ondonemoving : function() {
			this.releaseLock();
		},

		getLock : function() {
			if (this.isBlocked)
				return false;
			return this.isBlocked = true;
		},

		releaseLock : function() {
			this.isBlocked = false;
		}
	};
</script>
<body>
<div id="rocket"></div>
<div style="position: absolute; top: 110px">
	<div>
		<input type="button" onclick='doInterval("rocket")' value='doInterval("rocket")' /> 
		<span id="monitor1"></span>
	</div>
	<div>
		<input type="button" onclick='doTimeout("rocket")' value='doTimeout("rocket")' /> 
		<span id="monitor2"></span>
	</div>
</div>


<!-- 

http://www.w3schools.com/jsref/met_win_setinterval.asp
http://www.w3schools.com/js/js_timing.asp

-->